#include "operators.h"
#include "calls.h"
#include "list.h"
#include "../../semantics/parentdata.h"
#include "../../semantics/method.h"
#include "../../semantics/field.h"
#include "../../semantics/error.h"
#include "../../semantics/visitordata.h"
#include "../../semantics/classsemantic.h"
#include "../../code/callfactory.h"
#include "../../code/opcodes.h"



void  OperatorNode::write(GraphStream * s)
{
 this->accept(s);
 std::string arity="Complex operator";
 if (m_args.size()==1) arity="Unary operator";
 if (m_args.size()==2) arity="Binary operator";
 if (m_args.size()==3) arity="Ternary operator";
 fprintf(s->stream,"\tnode_%d [label=\"(%d,%d)\\n %s \\\"%s\\\" \" shape=\"rectangle\"]\n",this->number(),this->line(),this->position(),arity.c_str(),m_name.c_str());
 for (unsigned int i=0;i<m_args.size();i++)
 {
  m_args[i]->write(s);
  fprintf(s->stream,"\tnode_%d -> node_%d\n",this->number(),m_args[i]->number());
 }
}

OperatorNode::~OperatorNode()
{
	if (isOwningData())
	{
	 for (unsigned int i=0;i<m_args.size();i++)
	 {
      delete m_args[i];
	 }
	}
	delete m_behaviour;
}


bool OperatorNode::transformCode(ParentData * data)
{
	data->setCurrentOperator(this);
	m_transformation_behaviour=NULL;
	bool result=m_behaviour->transformCode(data);
	if (m_transformation_behaviour!=NULL && result)
	{
		delete m_behaviour;
		m_behaviour=m_transformation_behaviour;
	}
	return result;
}

bool AssignmentCommand::transformCode(ParentData * data)
{
  CurrentOperatorPtr ptr;
  data->getOp(ptr);
  AbstractNode * firstArg=ptr->args()[0];
  bool error=false;
  bool canTransform=firstArg->canBeTransformedFromAssignment(data,&error);
  if (!error && canTransform)
  {
		//If it is an array access operator, transform to array put
		if (firstArg->isOperator())
		{
			ptr->setLiteralName("[]:=");
			ptr->setTransformationBehaviour(new ArrayAssignment());
			OperatorNode * old=static_cast<OperatorNode*>(firstArg);
			old->disown();
			std::vector<AbstractNode*> & args=ptr->args();
			args[0]=old->args()[1];
			args.insert(args.begin(),old->args()[0]);
			delete old;
		}
		//Otherwise it is a field put, so we can hust transform it
		else
		{
			AttributeAccess * old=static_cast<AttributeAccess*>(firstArg);
			ptr->setLiteralName("put_field");
			ptr->setTransformationBehaviour(new FieldAssignment());
			AbstractNode * arg1=old->expression();
			FieldAccess * arg2=old->createFieldAccess();
			std::vector<AbstractNode*> & args=ptr->args();
			args[0]=arg2;
			args.insert(args.begin(),arg1);
			delete old;
		}
  }
  return !error;
}
bool   OperatorNode::isResultReturn()
{
 return m_behaviour->isResultReturn(this);
}

bool OperatorCommand::isResultReturn(OperatorNode * node)
{
  return false;
}
bool AssignmentCommand::isResultReturn(OperatorNode * node)
{
	AbstractNode * argnode=node->args()[0];
	if (argnode->isIdentifier())
	{
		std::string strings=static_cast<IdentifierNode*>(argnode)->data();
		return strings=="RESULT";
	}
	else
		return false;
}
ArrayAssignment::~ArrayAssignment()
{
	delete m_call_delegate;
}

FieldAssignment::~FieldAssignment()
{
	for (unsigned int i=0;i<m_delegates.size();i++)
		delete m_delegates[i];
}

AssignmentCommand::~AssignmentCommand()
{
	for (unsigned int i=0;i<m_delegates.size();i++)
		delete m_delegates[i];
}

OperatorCommand::~OperatorCommand()
{
}

bool OperatorCommand::transformCode(ParentData * data)
{
	CurrentOperatorPtr ptr;
	data->getOp(ptr);
	return true;
}

bool OperatorNode::canBeTransformedFromAssignment(ParentData * data, bool * error)
{
	return m_behaviour->canBeTransformedFromAssignment(data,error);
}

bool OperatorCommand::canBeTransformedFromAssignment(ParentData * data, bool * error)
{
    return false;
}

bool ArrayGetCommand::canBeTransformedFromAssignment(ParentData * data, bool * error)
{
	return true;
}

bool OperatorNode::isOperator()
{
	return true;
}

bool ArrayAssignment::checkLogic(ParentData * data)
{
	CurrentOperatorPtr ptr;
	data->getOp(ptr);
	return true;
}

bool FieldAssignment::checkLogic(ParentData * data)
{
	CurrentOperatorPtr ptr;
	data->getOp(ptr);
	return true;
}


bool AssignmentCommand::checkLogic(ParentData * data)
{
	CurrentOperatorPtr ptr;
	data->getOp(ptr);
	AbstractNode * farg=ptr->args()[0];
	bool test=farg->isLValue(data);
	if (test==false)
	{
		data->Classes->add(new LeftOperandIsNotLValue(&(*ptr)));
		return false;
	}
	return true;
}

bool OperatorCommand::checkLogic(ParentData * data)
{
	CurrentOperatorPtr ptr;
	data->getOp(ptr);
	data->Classes->add(new OperatorMakesNoSense(&(*ptr)));
	return false;
}


bool OperatorNode::checkLogic(ParentData * data)
{
	data->setCurrentOperator(this);
	bool result=m_behaviour->checkLogic(data);
	return result;
}

void OperatorCommand::checkCommonErrors(ParentData * data)
{
	CurrentOperatorPtr ptr;
	data->getOp(ptr);
	m_type=UNKNOWN_TYPE;
}

std::string OperatorCommand::getType(ParentData * data)
{
	return m_type;
}

void OperatorNode::checkCommonErrors(ParentData * data)
{
	if (m_visited==false)
	{
	data->setCurrentOperator(this);
	m_behaviour->checkCommonErrors(data);
	m_visited=true;
	}
	else m_visited=true;
}

std::string OperatorNode::getType(ParentData * data)
{
	data->setCurrentOperator(this);
	m_behaviour->checkCommonErrors(data);
	return m_behaviour->getType(data);
}


#define fArgType (types[0])
#define sArgType (types[1])
#define tArgType (types[2])

void ArrayAssignment::checkCommonErrors(ParentData * data)
{
	CurrentOperatorPtr ptr;
	data->getOp(ptr);

	std::string * types=new std::string[3]; 

	for (int i=0;i<3;i++)
	{
	 types[i]=ptr->args()[i]->getType(data);
	}
	
	ClassSemantic * fSem=data->Classes->getClassByName(fArgType);
	ClassSemantic * sSem=data->Classes->getClassByName(sArgType);
	ClassSemantic * tSem=data->Classes->getClassByName(tArgType);

	if (fSem && (sSem || isVoidIdentifier(ptr->args()[1]) ) && (tSem || isVoidIdentifier(ptr->args()[2])))
	{
		Method * meth=fSem->getArrayPutOperator(sSem,tSem,data->Classes);
		if (meth)
		{
			if (meth->isAvailable(data->CurrentClass->cnode()->name(),data->Classes)==false)
			{
				data->Classes->add(new MethodIsInaccessible(&(*ptr),meth->m_realname,data->CurrentClass->cnode()->name()));
			}
			m_pop_result=meth->returnType()!=NULL;
			Compound * cmpnd=new Compound(YYLTYPE(),"AbstractNode");
			
			m_pop_result=meth->returnType()!=NULL;

			cmpnd->add(ptr->args()[1]);
			cmpnd->add(ptr->args()[2]);
			m_call_delegate=createCallInformation(ptr->args()[0],fSem,meth,cmpnd,data);
			delete cmpnd;
		}
		else
		{
			data->Classes->add( new OperatorOverloadNotFound(ptr->args()[0],"[]:=",fArgType,sArgType,tArgType));
		}
	}
	else
	{
		if (fArgType=="VOID")
		{
			data->Classes->add(new VoidUsedInExpression(ptr->args()[0]));
		}
		if (sArgType=="VOID")
		{
			data->Classes->add(new VoidUsedInExpression(ptr->args()[1]));
		}
		if (tArgType=="VOID")
		{
			data->Classes->add(new VoidUsedInExpression(ptr->args()[2]));
		}
	}
	delete[] types;
	m_type="VOID";
}

#undef fArgType
#undef sArgType 
#undef tArgType 

void ArrayAssignment::fillConstant(ParentData * data)
{
	CurrentOperatorPtr ptr;
	data->getOp(ptr);
	ptr->args()[0]->fillConstant(data);
	m_call_delegate->fillConstant(data);
}
void ArrayAssignment::produceCode(ParentData * data)
{
	CurrentOperatorPtr ptr;
	data->getOp(ptr);
	ptr->args()[0]->produceCode(data);
	m_call_delegate->produceCode(data);
	if (m_pop_result)
		data->currentFile()->write(POP);
}

void FieldAssignment::checkCommonErrors(ParentData * data)
{
	CurrentOperatorPtr ptr;
	data->getOp(ptr);

	m_type="VOID";

	//Check, whether field is available
	FieldAccess* acc=static_cast<FieldAccess*>(ptr->args()[1]);
	if (acc->field()->isAvailable(data->CurrentClass->cnode()->name(),data->Classes)==false)
	{
		data->Classes->add( new FieldIsInaccessible(&(*ptr),acc->fieldName(),data->CurrentClass->cnode()->name()));
	}


	std::string  tArgType=ptr->args()[2]->getType(data);
	ClassSemantic * tSem=data->Classes->getClassByName(tArgType);


	//Check whether void identifier is used
	if (isVoidIdentifier(ptr->args()[2]))
	{
		m_delegates.push_back(new NullReference());
		return;
	}
	
	//If void is used in expression
	if (tArgType=="VOID")
	{
	  data->Classes->add(new VoidUsedInExpression(ptr->args()[2]));
	  return;
	}

	ClassSemantic * fSem=data->Classes->getClassByName(acc->field()->m_type);
	if (tSem && fSem)
	{
	 selectAssignmentConversion(fSem,tSem,data,ptr->args()[2],&(*ptr),m_delegates);
	}
}

void FieldAssignment::fillConstant(ParentData * data)
{
	CurrentOperatorPtr ptr;
	data->getOp(ptr);

	ptr->args()[0]->fillConstant(data);
	FieldAccess* acc=static_cast<FieldAccess*>(ptr->args()[1]);
	
	std::string classname,name,descriptor;
	acc->field()->getRefInfo(classname,name,descriptor);
	m_fieldref=data->currentTable()->createFieldRef(classname,name,descriptor);
	
	for (unsigned int i=0;i<m_delegates.size();i++)
		m_delegates[i]->fillConstant(data);
}


void FieldAssignment::produceCode(ParentData * data)
{
	CurrentOperatorPtr ptr;
	data->getOp(ptr);
	
	ptr->args()[0]->produceCode(data);
	
	for (unsigned int i=0;i<m_delegates.size();i++)
		m_delegates[i]->produceCode(data);

	JBFile * file=data->currentFile();
	file->write(PUTFIELD);
	file->write(m_fieldref);
}

void ArrayGetCommand::checkCommonErrors(ParentData * data)
{
  CurrentOperatorPtr ptr;
  data->getOp(ptr);
  std::string  fArgType=ptr->args()[0]->getType(data);
  std::string  sArgType=ptr->args()[1]->getType(data);

  ClassSemantic * fSem=data->Classes->getClassByName(fArgType);
  ClassSemantic * sSem=data->Classes->getClassByName(sArgType);
  if (fSem && sSem)
  {
	  Method * meth=fSem->getBinaryOperator("[]",sSem,data->Classes);
	  if (meth)
	  {
		    //Check for ARRAY::ARRAYGET (for adding checked cast)
			std::string classaname,name,descriptor;
			meth->getRefInfo(classaname,name,descriptor);
			if (name=="ARRAYGET" && descriptor=="(LINTEGER;)Ljava/lang/Object;")
			{
				m_checked_cast=true;
				m_conversion_class=meth->returnType()->partialName();
			}

			if (meth->isAvailable(data->CurrentClass->cnode()->name(),data->Classes)==false)
			{
				data->Classes->add(new MethodIsInaccessible(&(*ptr),meth->m_realname,data->CurrentClass->cnode()->name()));
			}
			Compound * cmpnd=new Compound(YYLTYPE(),"AbstractNode");
			
			cmpnd->add(ptr->args()[1]);
			m_call_delegate=createCallInformation(ptr->args()[0],fSem,meth,cmpnd,data);
			delete cmpnd;
			if (meth->returnType())
				m_type=meth->returnType()->fullName();
			else
				m_type="VOID";
	   }
	   else
	   {
			data->Classes->add( new OperatorOverloadNotFound(ptr->args()[0],"[]",fArgType,sArgType));
	   }
  }
  else
  {
   if (fArgType=="VOID")
   {
	 data->Classes->add(new VoidUsedInExpression(ptr->args()[0]));
   }
   if (sArgType=="VOID")
   {
	 data->Classes->add(new VoidUsedInExpression(ptr->args()[1]));
   }
   m_type="VOID";
  }
}
void ArrayGetCommand::fillConstant(ParentData * data)
{
  CurrentOperatorPtr ptr;
  data->getOp(ptr);
  ptr->args()[0]->fillConstant(data);
  m_call_delegate->fillConstant(data);
  if (m_checked_cast)
	  m_check_class=data->currentTable()->createClass(m_conversion_class);
}

void ArrayGetCommand::produceCode(ParentData * data)
{
  CurrentOperatorPtr ptr;
  data->getOp(ptr);
  ptr->args()[0]->produceCode(data);
  m_call_delegate->produceCode(data);
  if (m_checked_cast)
  {
	  data->currentFile()->write(CHECKCAST);
	  data->currentFile()->write(m_check_class);
  }
}

void AssignmentCommand::checkCommonErrors(ParentData * data)
{
  m_type="VOID";
  CurrentOperatorPtr ptr;
  data->getOp(ptr);
  
  std::string  fArgType=ptr->args()[0]->getType(data);
  std::string  sArgType=ptr->args()[1]->getType(data);
  
  //Check for assignment to void
  if (fArgType=="VOID")
  {
	  data->Classes->add(new VoidUsedInExpression(ptr->args()[0]));
	  if (sArgType=="VOID" && isVoidIdentifier(ptr->args()[1])==false)
			data->Classes->add(new VoidUsedInExpression(ptr->args()[1]));
	  return;	  
  }
  //Check if left operand is not an lvalue
  if (ptr->args()[0]->isIdentifier()==false)
  {
	data->Classes->add(new LeftOperandIsNotLValue(ptr->args()[0]));
	return;
  }
  //Check, whether local variable exists
  std::string localvarname=static_cast<IdentifierNode*>(ptr->args()[0])->data();
  m_local_index=data->CurrentMethod->getLocalNumberByName(localvarname);
  if (m_local_index==-1)
  {
	data->Classes->add(new LocalVariableNotFound(static_cast<IdentifierNode*>(ptr->args()[0])));
	return;
  }
  //Check assignment of void
  if (isVoidIdentifier(ptr->args()[1]))
  {
	  m_delegates.push_back(new NullReference());
	  return;
  }

  //Check common case
  ClassSemantic * fSem=data->Classes->getClassByName(fArgType);
  ClassSemantic * sSem=data->Classes->getClassByName(sArgType);
  selectAssignmentConversion(fSem,sSem,data,ptr->args()[1],&(*ptr),m_delegates);  
}


void AssignmentCommand::fillConstant(ParentData * data)
{
 CurrentOperatorPtr ptr;
 data->getOp(ptr);
 for (unsigned int i=0;i<m_delegates.size();i++)
	 m_delegates[i]->fillConstant(data);
}

void AssignmentCommand::produceCode(ParentData * data)
{
 CurrentOperatorPtr ptr;
 data->getOp(ptr);
 for (unsigned int i=0;i<m_delegates.size();i++)
	 m_delegates[i]->produceCode(data);
 JBFile * file=data->currentFile();
 file->write(ASTORE);
 file->write(m_local_index);
}

ArrayGetCommand::~ArrayGetCommand()
{
 delete m_call_delegate;
}

CommonOperatorCommand::~CommonOperatorCommand()
{
 delete m_call_delegate;

}

void CommonOperatorCommand::checkCommonErrors(ParentData * data)
{
  CurrentOperatorPtr ptr;
  data->getOp(ptr);
  OperatorNode * curnode=&(*ptr);
  std::string  fArgType=ptr->args()[0]->getType(data);
  std::string  sArgType=ptr->args()[1]->getType(data);

  ClassSemantic * fSem=data->Classes->getClassByName(fArgType);
  ClassSemantic * sSem=data->Classes->getClassByName(sArgType);
  if (fSem && sSem)
  {
	  Method * meth=fSem->getBinaryOperator(ptr->name(),sSem,data->Classes);
	  if (meth)
	  {
			if (meth->isAvailable(data->CurrentClass->cnode()->name(),data->Classes)==false)
			{
				data->Classes->add(new MethodIsInaccessible(&(*ptr),meth->m_realname,data->CurrentClass->cnode()->name()));
			}
			Compound * cmpnd=new Compound(YYLTYPE(),"AbstractNode");
			
			cmpnd->add(ptr->args()[1]);
			m_call_delegate=createCallInformation(ptr->args()[0],fSem,meth,cmpnd,data);
			delete cmpnd;
			if (meth->returnType())
				m_type=meth->returnType()->fullName();
			else
				m_type="VOID";
	   }
	   else
	   {
			data->Classes->add( new OperatorOverloadNotFound(ptr->args()[0],ptr->name(),fArgType,sArgType));
	   }
  }
  else
  {
   if (fArgType=="VOID")
   {
	 data->Classes->add(new VoidUsedInExpression(ptr->args()[0]));
   }
   if (sArgType=="VOID")
   {
	 data->Classes->add(new VoidUsedInExpression(ptr->args()[1]));
   }
   m_type="VOID";
  }
}

void CommonOperatorCommand::fillConstant(ParentData * data)
{
  CurrentOperatorPtr ptr;
  data->getOp(ptr);

  ptr->args()[0]->fillConstant(data);
  m_call_delegate->fillConstant(data);
}

void CommonOperatorCommand::produceCode(ParentData * data)
{
  CurrentOperatorPtr ptr;
  data->getOp(ptr);

  ptr->args()[0]->produceCode(data);
  m_call_delegate->produceCode(data);
}

NotCommand::~NotCommand()
{
	delete m_call_delegate;
}

void NotCommand::checkCommonErrors(ParentData * data)
{
  CurrentOperatorPtr ptr;
  data->getOp(ptr);
  std::string  fArgType=ptr->args()[0]->getType(data);

  ClassSemantic * fSem=data->Classes->getClassByName(fArgType);
  if (fSem)
  {
	  Method * meth=fSem->getUnaryOperator(ptr->name());
	  if (meth)
	  {
			if (meth->isAvailable(data->CurrentClass->cnode()->name(),data->Classes)==false)
			{
				data->Classes->add(new MethodIsInaccessible(&(*ptr),meth->m_realname,data->CurrentClass->cnode()->name()));
			}
			Compound * cmpnd=new Compound(YYLTYPE(),"AbstractNode");
			m_call_delegate=createCallInformation(ptr->args()[0],fSem,meth,cmpnd,data);
			delete cmpnd;
			if (meth->returnType())
				m_type=meth->returnType()->fullName();
			else
				m_type="VOID";
	   }
	   else
	   {
			data->Classes->add( new OperatorOverloadNotFound(ptr->args()[0],ptr->name(),fArgType));
	   }
  }
  else
  {
	data->Classes->add(new VoidUsedInExpression(ptr->args()[0]));
    m_type="VOID";
  }
}

void NotCommand::fillConstant(ParentData * data)
{
  CurrentOperatorPtr ptr;
  data->getOp(ptr);

  ptr->args()[0]->fillConstant(data);
  m_call_delegate->fillConstant(data);
}

void NotCommand::produceCode(ParentData * data)
{
  CurrentOperatorPtr ptr;
  data->getOp(ptr);

  ptr->args()[0]->produceCode(data);
  m_call_delegate->produceCode(data);
}

EqualityCommand::~EqualityCommand()
{
}

NonEqualityCommand::~NonEqualityCommand()
{
}



class OperatorCallDelegate : public MethodSelectDelegate
{
 private:
		 AbstractNode * m_node;
 public:
		inline OperatorCallDelegate(AbstractNode * n)
		{
			m_node=n;
		}
};



CompareCommand::~CompareCommand()
{
	for (unsigned int i=0;i<m_delegates.size();i++)
		delete m_delegates[i];
	delete m_default_comparison;
}

void CompareCommand::setDefaultComparison()
{
	m_delegates.push_back(m_default_comparison);
	m_default_comparison=NULL;
}
void CompareCommand::checkCommonErrors(ParentData * fdata)
{
  CurrentOperatorPtr ptr;
  fdata->getOp(ptr);

  if (m_delegates.size()!=0)
	  return;
  myoperator=&(*ptr);
  m_type="BOOLEAN";
 
  classes=fdata->Classes;
  pdata=fdata;

  for (unsigned int i=0;i<2;i++)
  {
	this->data[i].node=ptr->args()[i];
	this->data[i].type=data[i].node->getType(fdata);
	this->data[i].sclass=classes->getClassByName(data[i].type);
  }

  

  if (data[0].sclass!=NULL && data[1].sclass!=NULL)
	  handleCommonCall();
  else
	  handleInvalidTypes();
}

void CompareCommand::handleInvalidTypes()
{
	//If first argument is void
	if (isVoidIdentifier(data[0].node))
	{
		m_delegates.push_back(new NullReference());
		if (isVoidIdentifier(data[1].node))
		{
			m_delegates.push_back(new NullReference());
		}
		else
		{
			if (data[1].type=="VOID")
			{
				classes->add( new VoidUsedInExpression(data[1].node) );
			}
			else m_delegates.push_back(new NodeCodeProducer(data[1].node));
		}
		setDefaultComparison();
		return;
	}
	
	if (data[0].sclass==NULL)
	{
		//If second argument is incorrect exit
		if (data[1].sclass==NULL && !isVoidIdentifier(data[1].node))
			classes->add( new VoidUsedInExpression(data[1].node) );
		return;
	}

	//If first argumet is correct
	m_delegates.push_back( new NodeCodeProducer(data[0].node) );
	if (isVoidIdentifier(data[1].node))
	{
		m_delegates.push_back(new NullReference());
	}
	else
	{
		if (data[1].type=="VOID")
		{
		 classes->add( new VoidUsedInExpression(data[1].node) );
		}
		else m_delegates.push_back(new NodeCodeProducer(data[1].node));
	}
	setDefaultComparison();

}

void CompareCommand::handleCommonCall()
{
	Method * meth=data[0].sclass->getBinaryOperator(myoperator->name(),data[1].sclass,classes);
	
	if (data[0].type==data[1].type && meth==NULL)
	{
		m_delegates.push_back(new NodeCodeProducer(data[0].node));
		m_delegates.push_back(new NodeCodeProducer(data[1].node));
		setDefaultComparison();
		return;
	}

	bool isAncestor=classes->isAncestor(data[0].type,data[1].type);

	//If no conversion found
	if (!isAncestor && meth==NULL)
	{
		isAncestor=classes->isAncestor(data[1].type,data[0].type);
		if (!isAncestor)
		{
			classes->add(new IncompatibleTypes(myoperator,data[1].type,data[0].type));
		}
		m_delegates.push_back(new NodeCodeProducer(data[0].node));
		m_delegates.push_back(new NodeCodeProducer(data[1].node));
		setDefaultComparison();
		return;
	}

	//If conversion can be performed both way throw an error
	if (isAncestor && meth!=NULL)
	{
		classes->add(new ConvertConform(myoperator,data[0].type,data[1].type));
		return;
	}

	//If one is ancestor of other we should compare references
	if (isAncestor && meth==NULL)
	{
		m_delegates.push_back(new NodeCodeProducer(data[0].node));
		m_delegates.push_back(new NodeCodeProducer(data[1].node));
		setDefaultComparison();
		return;
	}

	m_delegates.push_back(new NodeCodeProducer(data[0].node));
	
	Compound * cmpnd=new Compound(YYLTYPE(),"AbstractNode");
	cmpnd->add(data[1].node);
	CallInformation * info=createCallInformation(data[0].node,data[0].sclass,meth,cmpnd,pdata);
	m_delegates.push_back(new CallMethodDelegate(info));
	delete cmpnd;
	//Determines a type
	if (meth->returnType())
		m_type=meth->returnType()->fullName();
	else
		m_type="VOID";

}
void CompareCommand::fillConstant(ParentData * data)
{
	CurrentOperatorPtr ptr;
	data->getOp(ptr);
	for (unsigned int i=0;i<m_delegates.size();i++)
		m_delegates[i]->fillConstant(data);
}
void CompareCommand::produceCode(ParentData * data)
{
	CurrentOperatorPtr ptr;
	data->getOp(ptr);
	for (unsigned int i=0;i<m_delegates.size();i++)
		m_delegates[i]->produceCode(data);
}

EqualityCommand::EqualityCommand()
{
	m_default_comparison=new CompareRefsEq();
}

NonEqualityCommand::NonEqualityCommand()
{
	m_default_comparison=new CompareRefsNeq();
}

void OperatorNode::fillConstant(ParentData * data)
{
	data->setCurrentOperator(this);
	m_behaviour->fillConstant(data);
}

void OperatorNode::produceCode(ParentData * data)
{
	data->setCurrentOperator(this);
	m_behaviour->produceCode(data);
}

/*! Fills a constant table for method
 */
void OperatorCommand::fillConstant(ParentData * data)
{
	CurrentOperatorPtr ptr;
	data->getOp(ptr);
}

/*! Produces a code for method
 */
void OperatorCommand::produceCode(ParentData * data)
{
	CurrentOperatorPtr ptr;
	data->getOp(ptr);
}
